/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gui.graphs3d;

import data.ConfigurationGraphData;
import data.ConfigurationGraphObject;
import java.text.DecimalFormat;
import java.util.Vector;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import main.ToEngineFacade;

/**
 *
 * @author Elad
 */
public class ConfigurationGraph extends Graph3D {

	private ConfigurationGraphData gData;

	public ConfigurationGraph(ConfigurationGraphData gData) {
		super();
		this.gData = gData;
		if (j3dInstalled){
			addGraphPoints();
			addAxises(new Positive3DAxis());
			setOrbitBehavior();
			Vector<TransformGroup> texts = new Vector();
			texts.add(add3DText("power", 1.11, 0.0, 0.0, 0.05, 0.05, 0.05));
			texts.add(add3DText("price", 0.01, 0, 1.11, 0.05, 0.05, 0.05));
			texts.add(add3DText("performance", 0.0, 1.02, 0.0, 0.05, 0.05, 0.05));        
			addRotationBehavior(texts);
			addTextMarks();
			//adding transperant box
			makeBox(1, 1, 1);
			finishGraphCreation();
		}
	}
	private void addTextMarks(){
		PointValues pMax = getMaxPoint(gData.get_ppp());
		PointValues pMin = getMinPoint(gData.get_ppp());
		DecimalFormat twoDForm = new DecimalFormat("#.####");
        if (pMax.equals(pMin)) {
            pMax = new PointValues(pMax.getX()+ pMin.getX(), pMax.getY() + pMin.getY(), pMax.getZ() + pMin.getZ(), pMax.getMsg());
            pMin = new PointValues(0, 0, 0, pMin.getMsg());
        }
		double intervalx =(pMax.getX()-pMin.getX())/10.0;
		double intervaly =(pMax.getY()-pMin.getY())/10.0;
		double intervalz =(pMax.getZ()-pMin.getZ())/10.0;
		Transform3D rotation = new Transform3D();
		rotation.rotY(Math.PI/2 );
		for (int i=0; i<11;  i++){
			add3DText( Double.valueOf(twoDForm.format(pMin.getX()+i * intervalx)) + "", (i * 0.1) + 0.03, -0.03, 0, 0.03, 0.03, 0.00);
			add3DText( Double.valueOf(twoDForm.format(pMin.getY()+i * intervaly)) + "", -0.03, (i * 0.1) -0.01, 0, 0.03, 0.03, 0.00);
			add3DText(Double.valueOf(twoDForm.format(pMin.getZ()+ i * intervalz)) + "", 0, -0.05,(i * 0.1) -0.03,0.0, 0.03, 0.03,rotation);
		}
	}

	@Override
	protected void addGraphPoints() {
		Vector<ConfigurationGraphObject> points = sortPoints(gData);
		Vector<PointValues> pointValues = normilizePoints(points);
		Vector<PointValues> unitedPoints = unitepoints(pointValues);
		for (int i = 0; i < unitedPoints.size(); i++) {
			PointValues p = unitedPoints.get(i);
			addPoint(p.getX(), p.getY(), p.getZ(), p.getMsg());
		}
	}

	protected Vector<PointValues> normilizePoints(Vector<ConfigurationGraphObject> points) {
		if (points.size() == 1) {
			Vector<PointValues> pValues = new Vector<PointValues>();
			ConfigurationGraphObject p = points.get(0);
			String msg = "Power Consumption: " + p.get_powerConsumption() + " Performance: " + p.get_performance() + " Price: " +
			p.get_price() + "\nSSD amount: " + p.get_amountSSD() + " SCSI amount: " + p.get_amountSCSI() + " SATA amount: " + p.get_amountSATA()+"\n";
			pValues.add(new PointValues(0.5f, 0.5f, 0.5f, msg));
			return pValues;
		}
		PointValues minPoint = getMinPoint(points);
		PointValues maxPoint = getMaxPoint(points);
		float deltaX = maxPoint.getX() - minPoint.getX();
		float deltaY = maxPoint.getY() - minPoint.getY();
		float deltaZ = maxPoint.getZ() - minPoint.getZ();
		Vector<PointValues> pValues = new Vector<PointValues>();
		float tempX, tempY, tempZ;
		String msg;
		ConfigurationGraphObject p;
		for (int i = 0; i < points.size(); i++) {
			p = points.get(i);
			tempX = ((float) (p.get_powerConsumption()) - minPoint.getX()) / deltaX;
			tempY =( ((float) (p.get_performance()) - minPoint.getY()) / deltaY);
			tempZ = ((float) (p.get_price()) - minPoint.getZ()) / deltaZ;
			msg = "Power Consumption: " + p.get_powerConsumption() + " Performance: " + p.get_performance() + " Price: " +
			p.get_price() + "\nSSD amount: " + p.get_amountSSD() + " SCSI amount: " + p.get_amountSCSI() + " SATA amount: " + p.get_amountSATA();
			pValues.add(new PointValues(tempX, tempY, tempZ, msg));
		}

		return pValues;
	}

	private PointValues getMaxPoint(Vector<ConfigurationGraphObject> points) {
		if (points.size() == 0) {
			return new PointValues(-1, -1, -1, "");
		}
		ConfigurationGraphObject p = points.get(0);
		float maxX = (float) p.get_powerConsumption(), maxY = (float) p.get_performance(), maxZ = (float) p.get_price();
		for (int i = 1; i < points.size(); i++) {
			p = points.get(i);
			if (maxX < p.get_powerConsumption()) {
				maxX = (float) p.get_powerConsumption();
			}
			if (maxY < p.get_performance()) {
				maxY = (float) p.get_performance();
			}
			if (maxZ < p.get_price()) {
				maxZ = (float) p.get_price();
			}
		}
		return new PointValues(maxX, maxY, maxZ, "");
	}

	private PointValues getMinPoint(Vector<ConfigurationGraphObject> points) {
		if (points.size() == 0) {
			return new PointValues(-1, -1, -1, "");
		}
		ConfigurationGraphObject p = points.get(0);
		float minX = (float) p.get_powerConsumption(), minY = (float) p.get_performance(), minZ = (float) p.get_price();
		for (int i = 1; i < points.size(); i++) {
			p = points.get(i);
			if (minX > p.get_powerConsumption()) {
				minX = (float) p.get_powerConsumption();
			}
			if (minY > p.get_performance()) {
				minY = (float) p.get_performance();
			}
			if (minZ > p.get_price()) {
				minZ = (float) p.get_price();
			}
		}
		return new PointValues(minX, minY, minZ, "");
	}

	public static void main(String[] args) {
		Vector<ConfigurationGraphObject> v = new Vector<ConfigurationGraphObject>();
		v.add(new ConfigurationGraphObject(1, 2, 3, 0, 0, 0));
		v.add(new ConfigurationGraphObject(4, 5, 6, 0, 0, 0));
		v.add(new ConfigurationGraphObject(7, 8, 9, 0, 0, 0));
		ConfigurationGraphData gd = new ConfigurationGraphData(v);
		new ConfigurationGraph(gd).setVisible(true);
	}
	@Override
	protected void setGraphLocation(Transform3D t) {
		t.setTranslation(new Vector3f(0.0f, -0.5f, -1f));//graph location in window

	}
}
